﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SmartMathLibrary;

namespace SmartMathLibrary.Filters.BloomFilter
{
    /// <summary>
    /// This class represents a normal BloomFilter.
    /// </summary>
    [Serializable]
    public class BloomFilter
    {
        /// <summary>
        /// This field holds the hash values.
        /// </summary>
        private UInt64 hashArray;

        /// <summary>
        /// Initializes a new instance of the <see cref="BloomFilter"/> class.
        /// </summary>
        public BloomFilter()
        {
            this.hashArray = 0;
        }

        /// <summary>
        /// Adds a new item to the filter.
        /// </summary>
        /// <param name="item">The item to add.</param>
        public void Add(IBloomFilter item)
        {
            if (item == (IBloomFilter) null)
            {
                throw new ArgumentNullException("item");
            }

            UInt64 itemHash = item.GetBloomHashCode();

            for (int i = 0; i < 64; i++)
            {
                if (BitOperations.IsBitSet(itemHash, i))
                {
                    this.hashArray = BitOperations.SetBit(this.hashArray, i);
                }
            }
        }

        /// <summary>
        /// Determines whether the virtual list contains the specified item.
        /// </summary>
        /// <param name="item">The item to check.</param>
        /// <returns>
        /// True if the virtual list contains the specified item otherwise, false.
        /// </returns>
        public bool Contains(IBloomFilter item)
        {
            if (item == (IBloomFilter) null)
            {
                throw new ArgumentNullException("item");
            }

            UInt64 itemHash = item.GetBloomHashCode();

            for (int i = 0; i < 64; i++)
            {
                if (BitOperations.IsBitSet(itemHash, i) && !(BitOperations.IsBitSet(this.hashArray, i)))
                {
                    return false;
                }
            }

            return true;
        }
    }
}